

#include "action.h"
#include "renderer.h"
#include "input.h"
#include "interpolationHelper.h"
#include "performActionNode.h"
#include "rootNode.h"

Action::Action(){

        bAlwaysUpdate=true;
        bPermanent=true;
        bHidden=true;
        bDragable=true;
        scale.x=48;
        scale.y=48;
        bTextured=true;
        textureID="icon_base";
        name="newAction";
        color=Vector4f(1.0,1.0,0.0,1.0);

        inPoint=0.0;
        outPoint=0.0;
        timeScale=1.0;

        bSkeletal=false;
        bRelative=false;


        listType.push_back("15TextInputButton");
        listName.push_back("name");
        listProp.push_back("NAME");
        listIcon.push_back("icon_base");

        listType.push_back("15TextInputButton");
        listName.push_back("timeScale");
        listProp.push_back("TIMESCALE");
        listIcon.push_back("icon_base");

        listType.push_back("15TextInputButton");
        listName.push_back("relative");
        listProp.push_back("BRELATIVE");
        listIcon.push_back("icon_base");

        listType.push_back("15TextInputButton");
        listName.push_back("skeletal");
        listProp.push_back("BSKELETAL");
        listIcon.push_back("icon_base");

        registerProperties();
}

Action::~Action(){}

void Action::registerProperties(){

        Button::registerProperties();
        createMemberID("TIMESCALE",&timeScale,this);
        createMemberID("BRELATIVE",&bRelative,this);
        createMemberID("BSKELETAL",&bSkeletal,this);
}

void Action::setup(){
    ListButton::setup();
}

void Action::update(double deltaTime){
}

void Action::mouseOver(){
    Button::mouseOver();
}

void Action::mouseDrag(){

    input->dragButton=this;
    setLocation(Vector3f(input->mouseX, input->mouseY,0));

}

void Action::finishDrag(){


    if (input->worldTarget && input->worldTarget->name!="ground" && input->worldTarget->baseNode){
        Node*   myRoot=NULL;
        Node*   myNode=NULL;
        myRoot=input->worldTarget->baseNode;
        //crawl down the node tree so that we append our action to the last node in the tree

        if (myRoot)
            while (myRoot->childNode){
                myRoot=myRoot->childNode;
                }

        renderer->actorInfo["17PerformActionNode"].actorReference->create();
        myNode=renderer->nodeList.back();

        myNode->location.x=myRoot->location.x;
        myNode->location.y=myRoot->location.y+50;
        myRoot->connectChild(myNode);
        myNode->setup();
        ((PerformActionNode*)myNode)->bRelative=bRelative;
        ((PerformActionNode*)myNode)->applyTo=input->worldTarget;
        ((PerformActionNode*)myNode)->myAction=name;



        }
    setLocation(initialLocation);

    if( input->hudTarget && input->hudTarget->isA("TimelineButton") )
    {
       ((TimelineButton*)input->hudTarget)->populateFromAction(this);
    }



}

void Action::clickedLeft(){
    Button::clickedLeft();
}

void Action::clickedRight(){
    ListButton::clickedLeft();
}

void Action::focusClick(){

}

void Action::deselect(int depth){

ListButton::deselect(depth);
}


void Action::create(){renderer->addAction(this);}

TiXmlElement* Action::save(TiXmlElement *root){

    TiXmlElement * element = new TiXmlElement( "Action" );
    element->SetAttribute("name", name);
    TiXmlText * text = new TiXmlText( typeid(*this).name() );
    element->LinkEndChild( text );

    std::map <std::string, memberID>::iterator it;

    //save standard properties
    for ( it=property.begin() ; it != property.end(); it++ )
      {
      TiXmlElement * property=new TiXmlElement(it->first);
      string value = memberToString(&it->second);
      property->LinkEndChild ( new TiXmlText(value));
      element->LinkEndChild( property );
      }

    //create KeyFrame Properties:
    for (uint i=0;i<keyFrames.size();i++){

        TiXmlElement * property=new TiXmlElement("KEYFRAME");
        TiXmlElement * locKeyProperty=new TiXmlElement("LOCATIONKEY");
        TiXmlElement * rotKeyProperty=new TiXmlElement("ROTATIONKEY");
        TiXmlElement * timeKeyProperty=new TiXmlElement("TIMEKEY");

            char locValue[64];
            sprintf(locValue,"vec3f %f %f %f",keyFrames[i]->locationKey.x,keyFrames[i]->locationKey.y,keyFrames[i]->locationKey.z);
            locKeyProperty->LinkEndChild ( new TiXmlText( locValue));

            property->LinkEndChild(locKeyProperty);

            char rotValue[64];
            sprintf(rotValue,"vec3f %f %f %f",keyFrames[i]->rotationKey.x,keyFrames[i]->rotationKey.y,keyFrames[i]->rotationKey.z);
            rotKeyProperty->LinkEndChild ( new TiXmlText( rotValue));

            property->LinkEndChild(rotKeyProperty);

            char timeValue[64];
            sprintf(timeValue,"float %f",keyFrames[i]->timeKey);
            timeKeyProperty->LinkEndChild ( new TiXmlText( timeValue));

            property->LinkEndChild(timeKeyProperty);

        if (bSkeletal){
            std::map <std::string, Matrix4f>::iterator it;
            for ( it=keyFrames[i]->boneMatrices.begin() ; it!=keyFrames[i]->boneMatrices.end() ; it++ ){
                TiXmlElement * boneProperty=new TiXmlElement("BONEMATRIX");
                boneProperty->SetAttribute("name", it->first);
                char boneValue[255];
                sprintf(boneValue,"mat4f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",  it->second.data[0],it->second.data[1],it->second.data[2],it->second.data[3],
                                                                                            it->second.data[4],it->second.data[5],it->second.data[6],it->second.data[7],
                                                                                            it->second.data[8],it->second.data[9],it->second.data[10],it->second.data[11],
                                                                                            it->second.data[12],it->second.data[13],it->second.data[14],it->second.data[15]);


                boneProperty->LinkEndChild ( new TiXmlText( boneValue));
                property->LinkEndChild(boneProperty);
                }
            }
        element->LinkEndChild( property );
        }

    return element;
}

void Action::load(TiXmlElement* myInfo){

    Button::load(myInfo);

    //Location/Rotation Keys
    for ( TiXmlElement * property=myInfo->FirstChildElement("KEYFRAME") ; property!=NULL; property=property->NextSiblingElement("KEYFRAME")){
        key* myKey = new key;

        //location
        TiXmlElement * locProperty=property->FirstChildElement("LOCATIONKEY");
        if (locProperty && locProperty->GetText()!=NULL){
            myKey->locationKey=readVector3f((char*)locProperty->GetText());
            cout << "found new locationKey: " << myKey->locationKey << endl;
            }
        else
            cout << "something wrong with KeyFrame" << endl;

        //rotation
        TiXmlElement * rotProperty=property->FirstChildElement("ROTATIONKEY");
        if (rotProperty && rotProperty->GetText()!=NULL){
            myKey->rotationKey=readVector3f((char*)rotProperty->GetText());
            cout << "found new rotationKey: " << myKey->rotationKey << endl;
            }
        else
            cout << "something wrong with KeyFrame" << endl;

        //time
        TiXmlElement * timeProperty=property->FirstChildElement("TIMEKEY");
        if (timeProperty && timeProperty->GetText()!=NULL){
            myKey->timeKey=readFloat((char*)timeProperty->GetText());
            cout << "found new timeKey: " << myKey->timeKey << endl;
            }
        else
            cout << "something wrong with KeyFrame" << endl;

        //bones
        TiXmlElement* boneProperty=property->FirstChildElement("BONEMATRIX");
        while (boneProperty){

            string boneName=boneProperty->Attribute("name");
            Matrix4f myMatrix=readMatrix4f((char*)boneProperty->GetText());
            myKey->boneMatrices[boneName]=myMatrix;
            boneProperty=boneProperty->NextSiblingElement();
            }
        keyFrames.push_back(myKey);
        cout << "loaded KeyFrames: " << keyFrames.size() << endl;
      }

}
